import { debounce } from 'lodash-es'
import { type Directive } from 'vue'

const map = new WeakMap()
const observer = new ResizeObserver((entries) => {
  entries.forEach((entry) => {
    const handler = map.get(entry.target)
    handler?.({
      width: entry.borderBoxSize[0].inlineSize,
      height: entry.borderBoxSize[0].blockSize
    })
  })
})

function skipFirstCall(fn: (...args: any) => void) {
  let called = false
  return function (this: unknown, ...args: any[]) {
    if (!called) {
      called = true
      return
    }
    fn.call(this, ...args)
  }
}

const resizeObserver: Directive = {
  mounted(el, binding) {
    const { value, modifiers } = binding
    let handler
    if (value) {
      handler = modifiers.debounce ? debounce(value, 300) : value
    }

    observer.observe(el)
    handler = handler && skipFirstCall(handler)
    map.set(el, handler)
  },
  unmounted(el) {
    map.delete(el)
    observer.unobserve(el)
  }
}

export { resizeObserver }
